package com.syh.jn.scm.domain.supplier.entity.base.upstream;


import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.util.validator.ValidationUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.domain.AbstractSimpleAggregate;
import com.syh.jn.scm.domain.supplier.repository.base.upstream.UpstreamCategoryReadRepository;
import com.syh.jn.scm.domain.supplier.repository.base.upstream.UpstreamReadRepository;
import com.syh.jn.scm.dto.supplier.base.upstream.cate.UpstreamCategoryMto;
import com.syh.jn.scm.dto.supplier.base.upstream.cate.UpstreamCategorySto;
import com.syh.jn.scm.exception.BusinessException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.util.List;

/**
 * 上游分类
 */
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class UpstreamCategory extends AbstractSimpleAggregate<Long> {
  /**
   * 状态（-1：停用 1：启用）
   */
  private Short status;
  /**
   * 上级分类id
   */
  private Long supId;
  /**
   * 归属id
   */
  private Long businessEntityId;
  /**
   * 自定义分类编码
   */
  private String code;
  /**
   * 父类目录
   */
  private String catalogCode;
  /**
   * 类别名称
   */
  private String name;
  /**
   * 排序等级
   */
  private Integer orderLevel;
  /**
   * 分类等级
   */
  private Integer cateLevel;
  /**
   * 父分类
   */
  private UpstreamCategory fatherCategorys;
  /**
   * 子分类
   */
  private List<UpstreamCategory> subCategorys;


  public UpstreamCategory(UpstreamCategorySto sto) {
    ExtAssert.notNull(sto, "对象为空");
    ValidationUtils.validate(sto);

    this.createTimeStamp = System.currentTimeMillis();
    this.status = 1;
    this.name = sto.getName();
    this.orderLevel = sto.getOrderLevel();
    this.businessEntityId = sto.getBusinessEntityId();
    //判断父级分类
    if (sto.getSupId() == null) {
      this.cateLevel = 0;
      this.supId = 0l;
    } else {
      this.supId = sto.getSupId();
      UpstreamCategoryReadRepository upCategoryQuery = (UpstreamCategoryReadRepository) SpringContextUtils.getBean(UpstreamCategoryReadRepository.class);
      UpstreamCategory fatherCategory = upCategoryQuery.getById(this.getSupId());
      ExtAssert.notNull(fatherCategory, "父级分类不存在");
      if (!fatherCategory.getStatus().equals(Short.valueOf("1"))) {
        throw new BusinessException("父级分类处于停用状态");
      }
      this.cateLevel = fatherCategory.getCateLevel() + 1;
    }
  }

  public void modify(UpstreamCategoryMto mto) {
    UpstreamCategoryReadRepository upCategoryQuery = (UpstreamCategoryReadRepository) SpringContextUtils.getBean(UpstreamCategoryReadRepository.class);
    if (mto.getSupId() != null && !Long.valueOf("0").equals(mto.getSupId())) {
      this.fatherCategorys = getFatherCates(upCategoryQuery, mto.getSupId());
      while (this.fatherCategorys != null){
        if(this.id == this.fatherCategorys.getId())
          throw new BusinessException("分类不能继承本身或子分类！");
        this.fatherCategorys = this.fatherCategorys.getFatherCategorys();
      }
    }

    ExtBeanUtils.copyProperties(mto, this, true);
    this.lastUpdateTimeStamp = System.currentTimeMillis();
  }


  /**
   * 启用分类
   */
  public void enabled() {
    UpstreamCategoryReadRepository upCateQuery = (UpstreamCategoryReadRepository) SpringContextUtils.getBean(UpstreamCategoryReadRepository.class);
    this.status = 1;
    if (!Long.valueOf("0").equals(this.supId)) {
      this.fatherCategorys = getFatherCates(upCateQuery, this.supId);
      updateFatherCates(this.fatherCategorys, this.status);
    }
  }

  /**
   * 停用分类
   */
  public void disabled() {
    UpstreamCategoryReadRepository upCateQuery = (UpstreamCategoryReadRepository) SpringContextUtils.getBean(UpstreamCategoryReadRepository.class);
    UpstreamReadRepository upQuery = (UpstreamReadRepository) SpringContextUtils.getBean(UpstreamReadRepository.class);

    this.subCategorys = upCateQuery.getList(Wrapper.build().append(Restrictions.rightLike("catalogCode", this.catalogCode)));
    this.subCategorys.forEach(subCate -> {
      if (upQuery.getCount(Wrapper.build().append(Restrictions.eq("categoryId", subCate.getId()))) > 0) {
        List<Upstream> queryList = upQuery.getList(Wrapper.build().append(Restrictions.eq("categoryId", subCate.getId())));
        queryList.forEach(good -> {
          if (good.getStatus() == 1)
            throw new BusinessException("该分类或所属子分类下的供应商正在使用，停用失败！");
        });
      }
    });
    this.status = -1;
    updateSubCates(this.subCategorys, this.status);
  }

  /**
   * 数据销毁
   */
  public void destroy() {
    UpstreamReadRepository upstreamSupplierQuery = (UpstreamReadRepository) SpringContextUtils.getBean(UpstreamReadRepository.class);
    UpstreamCategoryReadRepository upstreamCategoryQuery = (UpstreamCategoryReadRepository) SpringContextUtils.getBean(UpstreamCategoryReadRepository.class);
    Wrapper wrapper = Wrapper.build();
    wrapper.append(Restrictions.eq("categoryId", this.id));
    Integer upstreamCount = upstreamSupplierQuery.getCount(wrapper);
    if (upstreamCount > 0) {
      throw new BusinessException("该分类已经被供应商使用,不可以删除 !");
    }
    Wrapper cateWrapper = Wrapper.build();
    cateWrapper.append(Restrictions.eq("supId", this.id));
    Integer dsCate = upstreamCategoryQuery.getCount(cateWrapper);
    if (dsCate > 0) {
      throw new BusinessException("该分类被其它分类引用了,不可以删除,要删除的话,就先删除引用分类!");
    }
  }

  /**
   * 获取所有父分类
   */
  private UpstreamCategory getFatherCates(UpstreamCategoryReadRepository upCateQuery, Long id) {
    UpstreamCategory fatherCates = upCateQuery.getById(id);
    if (!Long.valueOf("0").equals(fatherCates.getSupId())) {
      fatherCates.setFatherCategorys(getFatherCates(upCateQuery, fatherCates.getSupId()));
    }
    return fatherCates;
  }

  /**
   * 停用子分类
   */
  public void updateSubCates(List<UpstreamCategory> subCates, Short status) {
    subCates.forEach(subCate -> {
      subCate.status = status;
    });
  }

  /**
   * 启用父分类
   */
  public void updateFatherCates(UpstreamCategory fatherCates, Short status) {
    fatherCates.status = status;
    if (fatherCates.fatherCategorys != null) {
      updateFatherCates(fatherCates.fatherCategorys, status);
    }
  }
}
